﻿#include "AppTool.h"

static AppTool* mAppTool = NULL;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "platform/android/jni/JniHelper.h"

#define CLASS_NAME "com/myamap/tool/AppTool"

void StartOnceLocation()
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "startOnceLocation", "()V"))
	{
		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID);
	}
}

void StartLocation(int interval)
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "startLocation", "(I)V"))
	{
		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID, (jint)interval);
	}
}

void StopLocation()
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "stopLocation", "(I)V"))
	{
		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID);
	}
}

void GetGeoCode(const string& addr, const string& city)
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "getGeoCode", "(Ljava/lang/String;Ljava/lang/String;)V"))
	{
		jstring jaddr = jmi.env->NewStringUTF(addr.c_str());
		jstring jcity = jmi.env->NewStringUTF(city.c_str());

		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID, jaddr, jcity);

		jmi.env->DeleteLocalRef(jaddr);
		jmi.env->DeleteLocalRef(jcity);
	}
}

void GetReGeoCode(double lat, double lng, float radius)
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "getReGeoCode", "(DDF)V"))
	{
		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID, (jdouble)lat, (jdouble)lng, (jfloat)radius);
	}
}

void PoiKeySearch(const string& keystr, const string& poitype, const string& city)
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "poiKeySearch", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"))
	{
		jstring jkeystr = jmi.env->NewStringUTF(keystr.c_str());
		jstring jpoitype = jmi.env->NewStringUTF(poitype.c_str());
		jstring jcity = jmi.env->NewStringUTF(city.c_str());

		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID, jkeystr, jpoitype, jcity);
	}
}

void PoiAroundSearch(const string& keystr, const string& poitype, double lat, double lng, int round, string city)
{
	JniMethodInfo jmi;
	if (JniHelper::getStaticMethodInfo(jmi, CLASS_NAME, "poiAroundSearch", "(Ljava/lang/String;Ljava/lang/String;DDILjava/lang/String;)V"))
	{
		jstring jkeystr = jmi.env->NewStringUTF(keystr.c_str());
		jstring jpoitype = jmi.env->NewStringUTF(poitype.c_str());
		jstring jcity = jmi.env->NewStringUTF(city.c_str());

		jmi.env->CallStaticVoidMethod(jmi.classID, jmi.methodID, jkeystr, jpoitype, (jdouble)lat, (jdouble)lng, (jint)round, jcity);
	}
}

extern "C"
{
	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onLocationUpdate(JNIEnv *env, jclass, jint jcode, jdouble jlat, jdouble jlng, jstring jformatAddr, jstring jprovince, jstring jcity, jstring jdistrict, jstring jstreet, jstring jnumber, jstring jpoi, jstring jadcode)
	{
		if (AppTool::getInstance()->getAmapLocationDelegate())
		{
			string formatAddr = JniHelper::jstring2string(jformatAddr);
			string province = JniHelper::jstring2string(jprovince);
			string city = JniHelper::jstring2string(jcity);
			string district = JniHelper::jstring2string(jdistrict);
			string street = JniHelper::jstring2string(jstreet);
			string number = JniHelper::jstring2string(jnumber);
			string poi = JniHelper::jstring2string(jpoi);
			string adcode = JniHelper::jstring2string(jadcode);

			AppTool::getInstance()->getAmapLocationDelegate()->onLocationUpdate((int)jcode, (double)jlat, (double)jlng, formatAddr, province, city, district, street, number, poi, adcode);
		}
	}

	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onOnceLocationEnd(JNIEnv *env, jclass, jint jcode, jdouble jlat, jdouble jlng, jstring jformatAddr, jstring jprovince, jstring jcity, jstring jdistrict, jstring jstreet, jstring jnumber, jstring jpoi, jstring jadcode)
	{
		if (AppTool::getInstance()->getAmapLocationDelegate())
		{
			string formatAddr = JniHelper::jstring2string(jformatAddr);
			string province = JniHelper::jstring2string(jprovince);
			string city = JniHelper::jstring2string(jcity);
			string district = JniHelper::jstring2string(jdistrict);
			string street = JniHelper::jstring2string(jstreet);
			string number = JniHelper::jstring2string(jnumber);
			string poi = JniHelper::jstring2string(jpoi);
			string adcode = JniHelper::jstring2string(jadcode);

			AppTool::getInstance()->getAmapLocationDelegate()->onOnceLocationEnd((int)jcode, (double)jlat, (double)jlng, formatAddr, province, city, district, street, number, poi, adcode);
		}
	}

	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onGetGeocodeAddress(JNIEnv *env, jclass, jint jcode, jdoubleArray jlatArray, jdoubleArray jlngArray, jobjectArray jformataddrArray, jobjectArray jprovinceArray, jobjectArray jcityArray, jobjectArray jdistrictArray, jobjectArray jtownArray, jobjectArray jstreetArray, jobjectArray jadcodeArray)
	{
		std::vector<GeocodeAddress> v_datas;

		if ((int)jcode == 0)
		{
			int psize = (int)env->GetArrayLength(jlatArray);

			v_datas.reserve(psize);

			jdouble* jlat = env->GetDoubleArrayElements(jlatArray, NULL);
			jdouble* jlng = env->GetDoubleArrayElements(jlngArray, NULL);

			for (int i = 0; i < psize; ++i)
			{
				GeocodeAddress data;

				data.lat = (double)jlat[i];
				data.lng = (double)jlng[i];

				jstring jformataddrstr = (jstring)env->GetObjectArrayElement(jformataddrArray, i);
				string formataddr = JniHelper::jstring2string(jformataddrstr);
				env->DeleteLocalRef(jformataddrstr);
				data.formatAddr = formataddr;

				jstring jprovincestr = (jstring)env->GetObjectArrayElement(jprovinceArray, i);
				string province = JniHelper::jstring2string(jprovincestr);
				env->DeleteLocalRef(jprovincestr);
				data.province = province;

				jstring jcitystr = (jstring)env->GetObjectArrayElement(jcityArray, i);
				string city = JniHelper::jstring2string(jcitystr);
				env->DeleteLocalRef(jcitystr);
				data.city = city;

				jstring jdistrictstr = (jstring)env->GetObjectArrayElement(jdistrictArray, i);
				string district = JniHelper::jstring2string(jdistrictstr);
				env->DeleteLocalRef(jdistrictstr);
				data.district = district;

				jstring jtownstr = (jstring)env->GetObjectArrayElement(jtownArray, i);
				string town = JniHelper::jstring2string(jtownstr);
				env->DeleteLocalRef(jtownstr);
				data.town = town;

				jstring jstreetstr = (jstring)env->GetObjectArrayElement(jstreetArray, i);
				string street = JniHelper::jstring2string(jstreetstr);
				env->DeleteLocalRef(jstreetstr);
				data.street = street;

				jstring jadcodestr = (jstring)env->GetObjectArrayElement(jadcodeArray, i);
				string adcode = JniHelper::jstring2string(jadcodestr);
				env->DeleteLocalRef(jadcodestr);
				data.adcode = adcode;

				v_datas.push_back(data);
			}

			env->ReleaseDoubleArrayElements(jlatArray, jlat, 0);
			env->ReleaseDoubleArrayElements(jlngArray, jlng, 0);
		}

		if (AppTool::getInstance()->getGeocodeDelegate())
		{
			AppTool::getInstance()->getGeocodeDelegate()->onGetGeocodeAddress((int)jcode, v_datas);
		}
	}

	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onGetRegeocodeInfo(JNIEnv *env, jclass, jint jcode, jstring jformatAddr, jstring jprovince, jstring jcity, jstring jdistrict, jstring jtown, jstring jstreet, jstring jadcode, jdoubleArray jpoilatArray, jdoubleArray jpoilngArray, jobjectArray jpoiinfoArray)
	{
		RegeocodeInfo regeocodeData;

		if ((int)jcode == 0)
		{
			int psize = (int)env->GetArrayLength(jpoilatArray);

			regeocodeData.v_Pois.reserve(psize);

			jdouble* jpoilat = env->GetDoubleArrayElements(jpoilatArray, NULL);
			jdouble* jpoilng = env->GetDoubleArrayElements(jpoilngArray, NULL);

			for (int i = 0; i < psize; ++i)
			{
				PoiInRegeocode data;

				data.lat = (double)jpoilat[i];
				data.lng = (double)jpoilng[i];

				jstring jpoiinfostr = (jstring)env->GetObjectArrayElement(jpoiinfoArray, i);
				string poiinfo = JniHelper::jstring2string(jpoiinfostr);
				env->DeleteLocalRef(jpoiinfostr);
				data.info = poiinfo;

				regeocodeData.v_Pois.push_back(data);

			}

			env->ReleaseDoubleArrayElements(jpoilatArray, jpoilat, 0);
			env->ReleaseDoubleArrayElements(jpoilngArray, jpoilng, 0);

			string formatAddr = JniHelper::jstring2string(jformatAddr);
			string province = JniHelper::jstring2string(jprovince);
			string city = JniHelper::jstring2string(jcity);
			string district = JniHelper::jstring2string(jdistrict);
			string town = JniHelper::jstring2string(jtown);
			string street = JniHelper::jstring2string(jstreet);
			string adcode = JniHelper::jstring2string(jadcode);

			regeocodeData.formatAddr = formatAddr;
			regeocodeData.province = province;
			regeocodeData.city = city;
			regeocodeData.district = district;
			regeocodeData.town = town;
			regeocodeData.street;
			regeocodeData.adcode = adcode;
		}

		if (AppTool::getInstance()->getGeocodeDelegate())
		{
			AppTool::getInstance()->getGeocodeDelegate()->onGetRegeocodeInfo((int)jcode, regeocodeData);
		}
	}

	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onPoiKeySearch(JNIEnv *env, jclass, jint jcode, jdoubleArray jlatArray, jdoubleArray jlngArray, jobjectArray jprovinceArray, jobjectArray jcityArray, jobjectArray jdistrictArray, jobjectArray jadcodeArray, jobjectArray jinfoArray)
	{
		std::vector<POISearchData> v_datas;

		if ((int)jcode == 0)
		{
			int psize = (int)env->GetArrayLength(jlatArray);

			v_datas.reserve(psize);

			jdouble* jlat = env->GetDoubleArrayElements(jlatArray, NULL);
			jdouble* jlng = env->GetDoubleArrayElements(jlngArray, NULL);

			for (int i = 0; i < psize; ++i)
			{
				POISearchData data;

				data.lat = (double)jlat[i];
				data.lng = (double)jlng[i];

				jstring jprovincestr = (jstring)env->GetObjectArrayElement(jprovinceArray, i);
				string province = JniHelper::jstring2string(jprovincestr);
				env->DeleteLocalRef(jprovincestr);
				data.province = province;

				jstring jcitystr = (jstring)env->GetObjectArrayElement(jcityArray, i);
				string city = JniHelper::jstring2string(jcitystr);
				env->DeleteLocalRef(jcitystr);
				data.city = city;

				jstring jdistrictstr = (jstring)env->GetObjectArrayElement(jdistrictArray, i);
				string district = JniHelper::jstring2string(jdistrictstr);
				env->DeleteLocalRef(jdistrictstr);
				data.district = district;

				jstring jadcodestr = (jstring)env->GetObjectArrayElement(jadcodeArray, i);
				string adcode = JniHelper::jstring2string(jadcodestr);
				env->DeleteLocalRef(jadcodestr);
				data.adcode = adcode;

				jstring jinfostr = (jstring)env->GetObjectArrayElement(jinfoArray, i);
				string info = JniHelper::jstring2string(jinfostr);
				env->DeleteLocalRef(jinfostr);
				data.info = info;

				v_datas.push_back(data);
			}

			env->ReleaseDoubleArrayElements(jlatArray, jlat, 0);
			env->ReleaseDoubleArrayElements(jlngArray, jlng, 0);
		}

		if (AppTool::getInstance()->getPoiSearchDelegate())
		{
			AppTool::getInstance()->getPoiSearchDelegate()->onPoiKeySearchEnd((int)jcode, v_datas);
		}
	}

	JNIEXPORT void JNICALL Java_com_myamap_tool_AppTool_onPoiAroundSearch(JNIEnv *env, jclass, jint jcode, jdoubleArray jlatArray, jdoubleArray jlngArray, jobjectArray jprovinceArray, jobjectArray jcityArray, jobjectArray jdistrictArray, jobjectArray jadcodeArray, jobjectArray jinfoArray)
	{
		std::vector<POISearchData> v_datas;

		if ((int)jcode == 0)
		{
			int psize = (int)env->GetArrayLength(jlatArray);

			v_datas.reserve(psize);

			jdouble* jlat = env->GetDoubleArrayElements(jlatArray, NULL);
			jdouble* jlng = env->GetDoubleArrayElements(jlngArray, NULL);

			for (int i = 0; i < psize; ++i)
			{
				POISearchData data;

				data.lat = (double)jlat[i];
				data.lng = (double)jlng[i];

				jstring jprovincestr = (jstring)env->GetObjectArrayElement(jprovinceArray, i);
				string province = JniHelper::jstring2string(jprovincestr);
				env->DeleteLocalRef(jprovincestr);
				data.province = province;

				jstring jcitystr = (jstring)env->GetObjectArrayElement(jcityArray, i);
				string city = JniHelper::jstring2string(jcitystr);
				env->DeleteLocalRef(jcitystr);
				data.city = city;

				jstring jdistrictstr = (jstring)env->GetObjectArrayElement(jdistrictArray, i);
				string district = JniHelper::jstring2string(jdistrictstr);
				env->DeleteLocalRef(jdistrictstr);
				data.district = district;

				jstring jadcodestr = (jstring)env->GetObjectArrayElement(jadcodeArray, i);
				string adcode = JniHelper::jstring2string(jadcodestr);
				env->DeleteLocalRef(jadcodestr);
				data.adcode = adcode;

				jstring jinfostr = (jstring)env->GetObjectArrayElement(jinfoArray, i);
				string info = JniHelper::jstring2string(jinfostr);
				env->DeleteLocalRef(jinfostr);
				data.info = info;

				v_datas.push_back(data);
			}

			env->ReleaseDoubleArrayElements(jlatArray, jlat, 0);
			env->ReleaseDoubleArrayElements(jlngArray, jlng, 0);
		}

		if (AppTool::getInstance()->getPoiSearchDelegate())
		{
			AppTool::getInstance()->getPoiSearchDelegate()->onPoiAroundSearch((int)jcode, v_datas);
		}
	}
}

#else

void StartOnceLocation()
{}

void StartLocation(int interval)
{}

void StopLocation()
{}

void GetGeoCode(const string& addr, const string& city)
{}

void GetReGeoCode(double lat, double lng, float radius)
{}

void PoiKeySearch(const string& keystr, const string& poitype, const string& city)
{}

void PoiAroundSearch(const string& keystr, const string& poitype, double lat, double lng, int round, string city)
{}

#endif

AppTool::AppTool() : m_pAmapLocationDelegate(NULL), m_pGeocodeDelegate(NULL), m_pPoiSearchDelegate(NULL)
{

}

AppTool::~AppTool()
{

}

AppTool* AppTool::getInstance()
{
	if (mAppTool == NULL)
	{
		mAppTool = new AppTool();
	}

	return mAppTool;
}

void AppTool::destroyInstance()
{
	CC_SAFE_RELEASE_NULL(mAppTool);
}

void AppTool::startOnceLocation()
{
	StartOnceLocation();
}

void AppTool::startLocation(int interval)
{
	StartLocation(interval);
}

void AppTool::stopLocation()
{
	StopLocation();
}

void AppTool::getGeocode(const string& addr, const string& city)
{
	GetGeoCode(addr, city);
}

void AppTool::getReGeocode(double lat, double lng, float radius)
{
	GetReGeoCode(lat, lng, radius);
}

void AppTool::poiKeySearch(const string& keystr, const string& poitype, const string& city)
{
	PoiKeySearch(keystr, poitype, city);
}

void AppTool::poiAroundSearch(const string& keystr, const string& poitype, double lat, double lng, int round, string city)
{
	PoiAroundSearch(keystr, poitype, lat, lng, round, city);
}
